package mcps

import (
	"context"
	"encoding/json"
	"fmt"
	"github.com/mark3labs/mcp-go/mcp"
	"github.com/mark3labs/mcp-go/server"
	"io"
	"net/http"
	"net/url"
	"strings"
	"time"
)

// PrometheusTool 启动一个提供 Prometheus 查询功能的 MCP 服务器
func PrometheusMCPServer() {
	s := server.NewMCPServer(
		"Prometheus 监控工具",
		"1.0.0",
	)

	// 添加 PromQL 查询工具
	queryTool := mcp.NewTool("prometheus_query",
		mcp.WithDescription("执行 PromQL 查询并返回结果"),
		mcp.WithString("query",
			mcp.Required(),
			mcp.Description("PromQL 查询表达式，例如: up 或 rate(node_cpu_seconds_total{mode=\"idle\"}[5m])"),
		),
		mcp.WithString("server",
			mcp.Description("Prometheus 服务器地址，默认为 http://192.168.210.109:8428"),
		),
	)
	s.AddTool(queryTool, prometheusQueryHandler)

	// 添加查询范围数据工具
	rangeQueryTool := mcp.NewTool("prometheus_query_range",
		mcp.WithDescription("在指定时间范围内执行 PromQL 查询"),
		mcp.WithString("query",
			mcp.Required(),
			mcp.Description("PromQL 查询表达式"),
		),
		mcp.WithString("start",
			mcp.Required(),
			mcp.Description("开始时间 (RFC3339 格式或相对时间，如 '1h' 表示1小时前)"),
		),
		mcp.WithString("end",
			mcp.Description("结束时间 (RFC3339 格式或相对时间，如 '5m' 表示5分钟前)，默认为当前时间"),
		),
		mcp.WithString("step",
			mcp.Description("步长 (如 '15s', '1m', '1h')，默认为 1m"),
		),
		mcp.WithString("server",
			mcp.Description("Prometheus 服务器地址，默认为 http://192.168.210.109:8428"),
		),
	)
	s.AddTool(rangeQueryTool, prometheusRangeQueryHandler)

	// 添加获取告警工具
	alertsTool := mcp.NewTool("prometheus_alerts",
		mcp.WithDescription("获取当前 Prometheus 告警信息"),
		mcp.WithString("server",
			mcp.Description("Prometheus 服务器地址，默认为 http://192.168.210.109:8428"),
		),
	)
	s.AddTool(alertsTool, prometheusAlertsHandler)

	// 添加获取目标状态工具
	targetsTool := mcp.NewTool("prometheus_targets",
		mcp.WithDescription("获取 Prometheus 监控目标状态"),
		mcp.WithString("state",
			mcp.Description("筛选目标状态 (active, dropped, all)，默认为 active"),
		),
		mcp.WithString("server",
			mcp.Description("Prometheus 服务器地址，默认为 http://192.168.210.109:8428"),
		),
	)
	s.AddTool(targetsTool, prometheusTargetsHandler)

	// 添加获取指标列表工具
	metricsTool := mcp.NewTool("prometheus_metrics",
		mcp.WithDescription("获取 Prometheus 可用指标列表"),
		mcp.WithString("match",
			mcp.Description("指标名称匹配模式，支持正则表达式"),
		),
		mcp.WithString("server",
			mcp.Description("Prometheus 服务器地址，默认为 http://192.168.210.109:8428"),
		),
	)
	s.AddTool(metricsTool, prometheusMetricsHandler)

	fmt.Println("Prometheus MCP 服务已启动...")
	if err := server.ServeStdio(s); err != nil {
		fmt.Printf("服务器错误: %v\n", err)
	}
}

// prometheusQueryHandler 处理 PromQL 查询请求
func prometheusQueryHandler(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
	query, ok := request.Params.Arguments["query"].(string)
	if !ok || query == "" {
		return mcp.NewToolResultError("query 参数必须是非空字符串"), nil
	}

	server, ok := request.Params.Arguments["server"].(string)
	if !ok || server == "" {
		server = "http://localhost:9090"
	}

	// 构建请求 URL
	u, err := url.Parse(fmt.Sprintf("%s/api/v1/query", server))
	if err != nil {
		return mcp.NewToolResultError(fmt.Sprintf("URL 解析错误: %v", err)), nil
	}

	q := u.Query()
	q.Set("query", query)
	u.RawQuery = q.Encode()

	// 发送请求
	httpClient := &http.Client{Timeout: 10 * time.Second}
	resp, err := httpClient.Get(u.String())
	if err != nil {
		return mcp.NewToolResultError(fmt.Sprintf("请求失败: %v", err)), nil
	}
	defer resp.Body.Close()

	// 读取响应
	body, err := io.ReadAll(resp.Body)
	if err != nil {
		return mcp.NewToolResultError(fmt.Sprintf("读取响应失败: %v", err)), nil
	}

	// 解析 JSON 响应
	var result map[string]interface{}
	if err := json.Unmarshal(body, &result); err != nil {
		return mcp.NewToolResultError(fmt.Sprintf("解析响应失败: %v", err)), nil
	}

	// 检查响应状态
	status, ok := result["status"].(string)
	if !ok || status != "success" {
		errorMsg := "未知错误"
		if errObj, ok := result["error"].(string); ok {
			errorMsg = errObj
		}
		return mcp.NewToolResultError(fmt.Sprintf("查询失败: %s", errorMsg)), nil
	}

	// 格式化响应
	formattedResult := formatPrometheusResponse(result)
	return mcp.NewToolResultText(formattedResult), nil
}

// prometheusRangeQueryHandler 处理范围查询请求
func prometheusRangeQueryHandler(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
	query, ok := request.Params.Arguments["query"].(string)
	if !ok || query == "" {
		return mcp.NewToolResultError("query 参数必须是非空字符串"), nil
	}

	start, ok := request.Params.Arguments["start"].(string)
	if !ok || start == "" {
		return mcp.NewToolResultError("start 参数必须是非空字符串"), nil
	}

	end, ok := request.Params.Arguments["end"].(string)
	if !ok || end == "" {
		end = "now"
	}

	step, ok := request.Params.Arguments["step"].(string)
	if !ok || step == "" {
		step = "1m"
	}

	server, ok := request.Params.Arguments["server"].(string)
	if !ok || server == "" {
		server = "http://localhost:9090"
	}

	// 处理相对时间
	startTime, err := parsePrometheusTime(start)
	if err != nil {
		return mcp.NewToolResultError(fmt.Sprintf("解析开始时间失败: %v", err)), nil
	}

	endTime, err := parsePrometheusTime(end)
	if err != nil {
		return mcp.NewToolResultError(fmt.Sprintf("解析结束时间失败: %v", err)), nil
	}

	// 构建请求 URL
	u, err := url.Parse(fmt.Sprintf("%s/api/v1/query_range", server))
	if err != nil {
		return mcp.NewToolResultError(fmt.Sprintf("URL 解析错误: %v", err)), nil
	}

	q := u.Query()
	q.Set("query", query)
	q.Set("start", startTime)
	q.Set("end", endTime)
	q.Set("step", step)
	u.RawQuery = q.Encode()

	// 发送请求
	httpClient := &http.Client{Timeout: 30 * time.Second}
	resp, err := httpClient.Get(u.String())
	if err != nil {
		return mcp.NewToolResultError(fmt.Sprintf("请求失败: %v", err)), nil
	}
	defer resp.Body.Close()

	// 读取响应
	body, err := io.ReadAll(resp.Body)
	if err != nil {
		return mcp.NewToolResultError(fmt.Sprintf("读取响应失败: %v", err)), nil
	}

	// 解析 JSON 响应
	var result map[string]interface{}
	if err := json.Unmarshal(body, &result); err != nil {
		return mcp.NewToolResultError(fmt.Sprintf("解析响应失败: %v", err)), nil
	}

	// 检查响应状态
	status, ok := result["status"].(string)
	if !ok || status != "success" {
		errorMsg := "未知错误"
		if errObj, ok := result["error"].(string); ok {
			errorMsg = errObj
		}
		return mcp.NewToolResultError(fmt.Sprintf("查询失败: %s", errorMsg)), nil
	}

	// 格式化响应
	formattedResult := formatPrometheusResponse(result)
	return mcp.NewToolResultText(formattedResult), nil
}

// prometheusAlertsHandler 处理获取告警请求
func prometheusAlertsHandler(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
	server, ok := request.Params.Arguments["server"].(string)
	if !ok || server == "" {
		server = "http://192.168.210.109:8428"
	}

	// 构建请求 URL
	u, err := url.Parse(fmt.Sprintf("%s/api/v1/alerts", server))
	if err != nil {
		return mcp.NewToolResultError(fmt.Sprintf("URL 解析错误: %v", err)), nil
	}

	// 发送请求
	httpClient := &http.Client{Timeout: 10 * time.Second}
	resp, err := httpClient.Get(u.String())
	if err != nil {
		return mcp.NewToolResultError(fmt.Sprintf("请求失败: %v", err)), nil
	}
	defer resp.Body.Close()

	// 读取响应
	body, err := io.ReadAll(resp.Body)
	if err != nil {
		return mcp.NewToolResultError(fmt.Sprintf("读取响应失败: %v", err)), nil
	}

	// 解析 JSON 响应
	var result map[string]interface{}
	if err := json.Unmarshal(body, &result); err != nil {
		return mcp.NewToolResultError(fmt.Sprintf("解析响应失败: %v", err)), nil
	}

	// 检查响应状态
	status, ok := result["status"].(string)
	if !ok || status != "success" {
		errorMsg := "未知错误"
		if errObj, ok := result["error"].(string); ok {
			errorMsg = errObj
		}
		return mcp.NewToolResultError(fmt.Sprintf("查询失败: %s", errorMsg)), nil
	}

	// 格式化告警信息
	formattedAlerts := formatAlertsResponse(result)
	return mcp.NewToolResultText(formattedAlerts), nil
}

// prometheusTargetsHandler 处理获取监控目标请求
func prometheusTargetsHandler(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
	state, ok := request.Params.Arguments["state"].(string)
	if !ok || state == "" {
		state = "active"
	}

	server, ok := request.Params.Arguments["server"].(string)
	if !ok || server == "" {
		server = "http://192.168.210.109:8428"
	}

	// 构建请求 URL
	u, err := url.Parse(fmt.Sprintf("%s/api/v1/targets", server))
	if err != nil {
		return mcp.NewToolResultError(fmt.Sprintf("URL 解析错误: %v", err)), nil
	}

	q := u.Query()
	if state != "all" {
		q.Set("state", state)
	}
	u.RawQuery = q.Encode()

	// 发送请求
	httpClient := &http.Client{Timeout: 10 * time.Second}
	resp, err := httpClient.Get(u.String())
	if err != nil {
		return mcp.NewToolResultError(fmt.Sprintf("请求失败: %v", err)), nil
	}
	defer resp.Body.Close()

	// 读取响应
	body, err := io.ReadAll(resp.Body)
	if err != nil {
		return mcp.NewToolResultError(fmt.Sprintf("读取响应失败: %v", err)), nil
	}

	// 解析 JSON 响应
	var result map[string]interface{}
	if err := json.Unmarshal(body, &result); err != nil {
		return mcp.NewToolResultError(fmt.Sprintf("解析响应失败: %v", err)), nil
	}

	// 检查响应状态
	status, ok := result["status"].(string)
	if !ok || status != "success" {
		errorMsg := "未知错误"
		if errObj, ok := result["error"].(string); ok {
			errorMsg = errObj
		}
		return mcp.NewToolResultError(fmt.Sprintf("查询失败: %s", errorMsg)), nil
	}

	// 格式化目标信息
	formattedTargets := formatTargetsResponse(result)
	return mcp.NewToolResultText(formattedTargets), nil
}

// prometheusMetricsHandler 处理获取指标列表请求
func prometheusMetricsHandler(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
	match, _ := request.Params.Arguments["match"].(string)

	server, ok := request.Params.Arguments["server"].(string)
	if !ok || server == "" {
		server = "http://192.168.210.109:8428"
	}

	// 构建请求 URL
	u, err := url.Parse(fmt.Sprintf("%s/api/v1/label/__name__/values", server))
	if err != nil {
		return mcp.NewToolResultError(fmt.Sprintf("URL 解析错误: %v", err)), nil
	}

	// 发送请求
	httpClient := &http.Client{Timeout: 10 * time.Second}
	resp, err := httpClient.Get(u.String())
	if err != nil {
		return mcp.NewToolResultError(fmt.Sprintf("请求失败: %v", err)), nil
	}
	defer resp.Body.Close()

	// 读取响应
	body, err := io.ReadAll(resp.Body)
	if err != nil {
		return mcp.NewToolResultError(fmt.Sprintf("读取响应失败: %v", err)), nil
	}

	// 解析 JSON 响应
	var result map[string]interface{}
	if err := json.Unmarshal(body, &result); err != nil {
		return mcp.NewToolResultError(fmt.Sprintf("解析响应失败: %v", err)), nil
	}

	// 检查响应状态
	status, ok := result["status"].(string)
	if !ok || status != "success" {
		errorMsg := "未知错误"
		if errObj, ok := result["error"].(string); ok {
			errorMsg = errObj
		}
		return mcp.NewToolResultError(fmt.Sprintf("查询失败: %s", errorMsg)), nil
	}

	// 获取指标列表
	data, ok := result["data"].([]interface{})
	if !ok {
		return mcp.NewToolResultError("响应格式错误"), nil
	}

	// 如果有匹配模式，过滤指标
	var metrics []string
	for _, m := range data {
		metricName, ok := m.(string)
		if !ok {
			continue
		}

		if match == "" || strings.Contains(metricName, match) {
			metrics = append(metrics, metricName)
		}
	}

	// 构建响应
	var sb strings.Builder
	sb.WriteString(fmt.Sprintf("找到 %d 个指标:\n\n", len(metrics)))
	for _, m := range metrics {
		sb.WriteString(m + "\n")
	}

	return mcp.NewToolResultText(sb.String()), nil
}

// 辅助函数

// parsePrometheusTime 解析 Prometheus 时间参数
func parsePrometheusTime(timeStr string) (string, error) {
	if timeStr == "now" {
		return time.Now().Format(time.RFC3339), nil
	}

	// 尝试解析为 RFC3339 格式
	if _, err := time.Parse(time.RFC3339, timeStr); err == nil {
		return timeStr, nil
	}

	// 尝试解析为相对时间
	duration, err := time.ParseDuration(timeStr)
	if err == nil {
		return time.Now().Add(-duration).Format(time.RFC3339), nil
	}

	return "", fmt.Errorf("无法解析时间: %s", timeStr)
}

// formatPrometheusResponse 格式化 Prometheus 查询响应
func formatPrometheusResponse(result map[string]interface{}) string {
	data, ok := result["data"].(map[string]interface{})
	if !ok {
		return "响应格式错误"
	}

	resultType, ok := data["resultType"].(string)
	if !ok {
		return "响应格式错误"
	}

	var sb strings.Builder
	sb.WriteString(fmt.Sprintf("结果类型: %s\n\n", resultType))

	switch resultType {
	case "vector":
		return formatVectorResult(data)
	case "matrix":
		return formatMatrixResult(data)
	case "scalar":
		return formatScalarResult(data)
	case "string":
		return formatStringResult(data)
	default:
		return fmt.Sprintf("不支持的结果类型: %s", resultType)
	}
}

// formatVectorResult 格式化向量结果
func formatVectorResult(data map[string]interface{}) string {
	result, ok := data["result"].([]interface{})
	if !ok {
		return "响应格式错误"
	}

	var sb strings.Builder
	sb.WriteString(fmt.Sprintf("找到 %d 个结果:\n\n", len(result)))

	for i, r := range result {
		item, ok := r.(map[string]interface{})
		if !ok {
			continue
		}

		metric, ok := item["metric"].(map[string]interface{})
		if !ok {
			continue
		}

		value, ok := item["value"].([]interface{})
		if !ok || len(value) != 2 {
			continue
		}

		sb.WriteString(fmt.Sprintf("结果 #%d:\n", i+1))
		sb.WriteString("  标签:\n")
		for k, v := range metric {
			sb.WriteString(fmt.Sprintf("    %s: %v\n", k, v))
		}

		timestamp, _ := value[0].(float64)
		valueStr, _ := value[1].(string)
		t := time.Unix(int64(timestamp), 0)
		sb.WriteString(fmt.Sprintf("  时间: %s\n", t.Format(time.RFC3339)))
		sb.WriteString(fmt.Sprintf("  值: %s\n\n", valueStr))
	}

	return sb.String()
}

// formatMatrixResult 格式化矩阵结果
func formatMatrixResult(data map[string]interface{}) string {
	result, ok := data["result"].([]interface{})
	if !ok {
		return "响应格式错误"
	}

	var sb strings.Builder
	sb.WriteString(fmt.Sprintf("找到 %d 个时间序列:\n\n", len(result)))

	for i, r := range result {
		series, ok := r.(map[string]interface{})
		if !ok {
			continue
		}

		metric, ok := series["metric"].(map[string]interface{})
		if !ok {
			continue
		}

		values, ok := series["values"].([]interface{})
		if !ok {
			continue
		}

		sb.WriteString(fmt.Sprintf("时间序列 #%d:\n", i+1))
		sb.WriteString("  标签:\n")
		for k, v := range metric {
			sb.WriteString(fmt.Sprintf("    %s: %v\n", k, v))
		}

		sb.WriteString(fmt.Sprintf("  数据点: %d\n", len(values)))
		if len(values) > 0 {
			sb.WriteString("  样本数据:\n")
			maxSamples := 5
			if len(values) < maxSamples {
				maxSamples = len(values)
			}

			for j := 0; j < maxSamples; j++ {
				point, ok := values[j].([]interface{})
				if !ok || len(point) != 2 {
					continue
				}

				timestamp, _ := point[0].(float64)
				valueStr, _ := point[1].(string)
				t := time.Unix(int64(timestamp), 0)
				sb.WriteString(fmt.Sprintf("    时间: %s, 值: %s\n", t.Format(time.RFC3339), valueStr))
			}

			if len(values) > maxSamples {
				sb.WriteString(fmt.Sprintf("    ... 还有 %d 个数据点\n", len(values)-maxSamples))
			}
		}
		sb.WriteString("\n")
	}

	return sb.String()
}

// formatScalarResult 格式化标量结果
func formatScalarResult(data map[string]interface{}) string {
	result, ok := data["result"].([]interface{})
	if !ok || len(result) != 2 {
		return "响应格式错误"
	}

	timestamp, _ := result[0].(float64)
	value, _ := result[1].(string)
	t := time.Unix(int64(timestamp), 0)

	var sb strings.Builder
	sb.WriteString("标量结果:\n")
	sb.WriteString(fmt.Sprintf("  时间: %s\n", t.Format(time.RFC3339)))
	sb.WriteString(fmt.Sprintf("  值: %s\n", value))

	return sb.String()
}

// formatStringResult 格式化字符串结果
func formatStringResult(data map[string]interface{}) string {
	result, ok := data["result"].([]interface{})
	if !ok || len(result) != 2 {
		return "响应格式错误"
	}

	timestamp, _ := result[0].(float64)
	value, _ := result[1].(string)
	t := time.Unix(int64(timestamp), 0)

	var sb strings.Builder
	sb.WriteString("字符串结果:\n")
	sb.WriteString(fmt.Sprintf("  时间: %s\n", t.Format(time.RFC3339)))
	sb.WriteString(fmt.Sprintf("  值: %s\n", value))

	return sb.String()
}

// formatAlertsResponse 格式化告警响应
func formatAlertsResponse(result map[string]interface{}) string {
	data, ok := result["data"].(map[string]interface{})
	if !ok {
		return "响应格式错误"
	}

	alerts, ok := data["alerts"].([]interface{})
	if !ok {
		return "响应格式错误"
	}

	var sb strings.Builder
	sb.WriteString(fmt.Sprintf("找到 %d 个告警:\n\n", len(alerts)))

	for i, a := range alerts {
		alert, ok := a.(map[string]interface{})
		if !ok {
			continue
		}

		labels, _ := alert["labels"].(map[string]interface{})
		annotations, _ := alert["annotations"].(map[string]interface{})
		state, _ := alert["state"].(string)
		activeAt, _ := alert["activeAt"].(string)
		value, _ := alert["value"].(string)

		sb.WriteString(fmt.Sprintf("告警 #%d:\n", i+1))
		sb.WriteString(fmt.Sprintf("  状态: %s\n", state))
		if activeAt != "" {
			sb.WriteString(fmt.Sprintf("  激活时间: %s\n", activeAt))
		}
		if value != "" {
			sb.WriteString(fmt.Sprintf("  值: %s\n", value))
		}

		sb.WriteString("  标签:\n")
		for k, v := range labels {
			sb.WriteString(fmt.Sprintf("    %s: %v\n", k, v))
		}

		sb.WriteString("  注释:\n")
		for k, v := range annotations {
			sb.WriteString(fmt.Sprintf("    %s: %v\n", k, v))
		}
		sb.WriteString("\n")
	}

	return sb.String()
}

// formatTargetsResponse 格式化监控目标响应
func formatTargetsResponse(result map[string]interface{}) string {
	data, ok := result["data"].(map[string]interface{})
	if !ok {
		return "响应格式错误"
	}

	activeTargets, activeOk := data["activeTargets"].([]interface{})
	droppedTargets, droppedOk := data["droppedTargets"].([]interface{})

	var sb strings.Builder

	if activeOk {
		sb.WriteString(fmt.Sprintf("活跃目标: %d\n\n", len(activeTargets)))
		for i, t := range activeTargets {
			target, ok := t.(map[string]interface{})
			if !ok {
				continue
			}

			scrapeUrl, _ := target["scrapeUrl"].(string)
			health, _ := target["health"].(string)
			lastError, _ := target["lastError"].(string)
			labels, _ := target["labels"].(map[string]interface{})

			sb.WriteString(fmt.Sprintf("目标 #%d:\n", i+1))
			sb.WriteString(fmt.Sprintf("  URL: %s\n", scrapeUrl))
			sb.WriteString(fmt.Sprintf("  健康状态: %s\n", health))
			if lastError != "" {
				sb.WriteString(fmt.Sprintf("  最后错误: %s\n", lastError))
			}

			sb.WriteString("  标签:\n")
			for k, v := range labels {
				sb.WriteString(fmt.Sprintf("    %s: %v\n", k, v))
			}
			sb.WriteString("\n")
		}
	}

	if droppedOk && len(droppedTargets) > 0 {
		sb.WriteString(fmt.Sprintf("丢弃的目标: %d\n\n", len(droppedTargets)))
		for i, t := range droppedTargets {
			target, ok := t.(map[string]interface{})
			if !ok {
				continue
			}

			discoveredLabels, _ := target["discoveredLabels"].(map[string]interface{})

			sb.WriteString(fmt.Sprintf("丢弃的目标 #%d:\n", i+1))
			sb.WriteString("  发现的标签:\n")
			for k, v := range discoveredLabels {
				sb.WriteString(fmt.Sprintf("    %s: %v\n", k, v))
			}
			sb.WriteString("\n")
		}
	}

	return sb.String()
}
